//哈希表，key_val:字符及其出现的下标
// class Solution {
// public:
//     int lengthOfLongestSubstring(string s) {
//         int len = s.size();
//         if (len == 0)
//             return 0;

//         int max_len = 1;
//         unordered_map<char, int> hash;
//         int left = 0, right = 0;
//         for (; right < len; right++)
//         {
//             if (!hash.count(s[right]))
//                 max_len = max(max_len, right - left + 1);
//             else
//             {
//                 int tmp_left = hash[s[right]] + 1;
//                 for (int i = left; i < tmp_left; i++)
//                     if (hash.count(s[i]))
//                         hash.erase(s[i]);
//                 left = tmp_left;
//             }

//             hash[s[right]] = right;
//         }
//         max_len = max(max_len, right - left);

//         return max_len;
//     }
// };

//哈希表，key_val:字符及其出现的次数
//（窗口内每个字符只能出现一次），如果出现多次，就缩小窗口
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len = s.size();
        if (len == 0)
            return 0;

        int max_len = 1;
        unordered_map<char, int> hash;
        int left = 0, right = 0;
        for (; right < len; right++)
        {
            hash[s[right]]++;

            while (hash[s[right]] > 1)  //这里必须利用right判断，因为只有right是把所有字符都走了一遍
                hash[s[left++]]--;
            
            max_len = max(max_len, right - left + 1);
        }
        
        return max_len;
    }
};